package middleware

import (
	"context"
	"strings"
	"time"

	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/monitor"
	"code.bydev.io/frameworks/byone/core/logc"
	"git.bybit.com/svc/stub/pkg/pb/cmd"
	"github.com/golang/protobuf/proto"
	"google.golang.org/grpc"
)

func LogServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
	logc.Infof(ctx, "[%s] start req: %+v", info.FullMethod, req)
	resp, err = handler(ctx, req)
	if err != nil {
		logc.Infof(ctx, "[%s] end resp: %+v, err: %+v", info.FullMethod, resp, err)
	} else {
		if info.FullMethod != "/bybit.kyc.admin.v1.AdminAPI/GetKycImage" {
			logc.Infof(ctx, "[%s] end resp: %+v", info.FullMethod, resp)
		}
	}
	return resp, err
}

func MetricsServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
	start := time.Now()
	methodSli := strings.Split(info.FullMethod, "/")
	method := methodSli[len(methodSli)-1]
	span, ctx := monitor.DefaultTrace(ctx, "GRPC", method)
	resp, err = handler(ctx, req)
	monitor.DefaultMetrics(start, span, err, "GRPC", method)
	return resp, err
}

func LogClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
	err := invoker(ctx, method, req, reply, cc, opts...)
	logMethod := method
	logReply := reply
	logReqStr := req
	if cmdReq, ok := req.(*cmd.Command); ok {
		logMethod = cmdReq.GetName()
		logReqStr = proto.MarshalTextString(cmdReq.GetArgs())
		if _, okReply := reply.(*cmd.CommandResponse); okReply {
			logReply = proto.MarshalTextString(reply.(*cmd.CommandResponse))
		}
	}
	if err != nil {
		logc.Errorw(
			ctx,
			"[LogClientInterceptor ERROR]",
			logc.Field("method", logMethod),
			logc.Field("req", logReqStr),
			logc.Field("err", err),
		)
		return err
	}
	logc.Infow(
		ctx,
		"[LogClientInterceptor INFO]",
		logc.Field("method", logMethod),
		logc.Field("req", logReqStr),
		logc.Field("resp", logReply),
	)
	return nil
}
